package roborally.program.command;

import java.util.NoSuchElementException;
import exception.IllegalPositionException;
import exception.IllegalPositionOnBoardException;
import roborally.factory.PhysicalAmountFactory;
import roborally.itemsonboard.Robot;
import roborally.program.text.TextProcedure;
import roborally.supporting.DefaultConstants;
import roborally.supporting.Direction;
import roborally.supporting.PhysicalAmount;
import roborally.supporting.Unit;
import roborally.usableitems.UsableWithBoard;
import be.kuleuven.cs.som.annotate.Basic;
import be.kuleuven.cs.som.annotate.Immutable;
import be.kuleuven.cs.som.annotate.Raw;


/**
 * A class representing a basic command that has a direct execution.
 * 
 * @invar (repeated) An ArgumentCommand must have legal arguments, as defined in the method canHaveAsArguments() at all times.
 * 		| this.canHaveAsArguments(this.getArguments())
 * @invar The execution procedure must be valid, as defined in canHaveAsExecutionProcedure()
 * 		| this.canHaveAsExecutionProcedure(this.getExecutionProcedure())
 * 
 * @author Molderez Tom, 2de bach Ingenieurswetenschappen Computerwetenschappen-Elektrotechniek and Reniers Jorn, 2de bach Ingenieurswetenschappen Werktuigkunde-Computerwetenschappen
 * @version 3.2
 *
 */
public class ExecutionCommand extends ArgumentCommand {
	
	/**
     * Creates a new ExecutionCommand.
     * 
     * @param executionProcedure The executionProcedure of this executionCommand.
     * @param arguments Extra arguments that might be needed for the basic commands.
     * @post The executionProcedure of the new ExecutionCommand will be the given procedure.
     * 		| (new this).getExecutionProcedure() == executionProcedure
     * @effect Has the same effect concerning arguments as the constructor of ArgumentCommand, the superclass of this ExecutionCommand.
     * 		| super(arguments)
     * @throws IllegalArgumentException (repeated)
	 * 		When the arguments are not valid according to isPossibleArguments().
	 * 		| !isPossibleArguments(arguments)
     * @throws IllegalArgumentException
     * 		When the executionProcedure is not valid according to canHaveAsExecutionProcedure().
     * 		| !canHaveAsExecutionProcedure(executionProcedure)
     * @throws IllegalArgumentException
     * 		When the given arguments are not valid for the command that would leave this constructor, according to 
     * 			canHaveAsArguments(), invoked after setting the procedure to the given procedure.
     * 		| !(new this).canHaveAsArguments(arguments)
     */
    public ExecutionCommand(ExecutionProcedure executionProcedure, Object...arguments) {
    	super(arguments);
    	if(!canHaveAsExecutionProcedure(executionProcedure))
    		throw new IllegalArgumentException("Illegal execution procedure");
        this.executionProcedure = executionProcedure;
        if(!canHaveAsArguments(this.getArguments()))
        	throw new IllegalArgumentException("Illegal arguments for the executioncommand: " + this.getExecutionProcedure());
    }
   
	/**
	 * Returns a ExecutionProcedure that represents this ExecutionCommand.
	 */
	@Basic @Raw @Immutable
	public ExecutionProcedure getExecutionProcedure() {
		return this.executionProcedure;
	}
	
	/**
	 * Controls if the executionProcedure is valid.
	 * 
	 * @param executionProcedure The executionProcedure to be controlled.
	 * @return False if the executionProcedure is null.
	 * 		| if executionProcedure == null
	 * 		|	then result == false
	 */
	@Raw
	public boolean canHaveAsExecutionProcedure(
			ExecutionProcedure executionProcedure) {
		return executionProcedure != null;
	}
	
	/**
	 * The executionProcedure of this ExecutionCommand.
	 */
	private final ExecutionProcedure executionProcedure;
	
	/**
	 * Controls if the given arguments are valid according to the current ExecutionProcedure.
	 * 
	 * @param arguments The arguments to be controlled.
	 * @return If this executionCommand has no valid ExecutionProcedure, and if the result of the version in 
	 * 			the superclass is false, then the result is also false.
	 * 		| if !this.canHaveAsExecutionProcedure(this.getExecutionProcedure())
	 * 		|	then if !super.canHaveAsArguments(arguments)
	 * 		|			then result == false
	 * @return False if this ExecutionCommand cannot have the arguments as defined at super.canHaveAsArguments()
	 * 		| if !super.canHaveAsArguments(arguments)
	 * 		|	then result == false
	 * @return False if the executionProcedure of this ExecutionCommand cannot have the arguments as defined at this.getExecutionProcedure().canHaveAsArguments()
	 * 		| if !this.getExecutionProcedure().canHaveAsArguments(arguments)
	 * 		|	then result == false
	 */
	@Override
	@Raw
	public boolean canHaveAsArguments(Object...arguments) {
		if(!this.canHaveAsExecutionProcedure(this.getExecutionProcedure()))
			return super.canHaveAsArguments(arguments);
		return super.canHaveAsArguments(arguments) && this.getExecutionProcedure().canHaveAsArguments(arguments);
	}
	
	/**
	 * Executes this ExecutionCommand. The actions depend on the ExecutionProcedure and the arguments.
	 * 
	 * @param robot The robot that must be manipulated.
	 * @effect Evokes the method execute() on the executionProcedure of this executionCommand, 
	 * 			with the given robot and the arguments of this executionCommand.
	 * 		| this.getExecutionProcedure().execute(robot, this.getArguments())
	 * @throws IllegalArgumentException (repeated)
	 * 		When the robot is not valid.
	 * 		| !canHaveForExecution(robot)
	 */
	@Override
	public void execute(Robot robot) throws IllegalArgumentException {
		if(!canHaveForExecution(robot))
			throw new IllegalArgumentException("Illegal Robot");
		this.getExecutionProcedure().execute(robot, this.getArguments()); // the class-invariant makes sure that there will be no exception thrown.
	}
	
	/**
	 *  Executes this executionProcedure only if minimumSteps is equal to currentSteps.
	 *  Returns currentSteps + 1.
	 *  
	 *  This method serves for executing a program step by step. The minimumSteps represent
	 *  the amount of executionCommands that are already executed. The currentSteps represent
	 *  the amount of executionCommands that are founded by search the entire program. Only when
	 *  both are equal, this method will invoke the method execute. In either case, this method
	 *  will return currnetSteps + 1  implying that a next executionCommand is been founded.
	 * 
	 * @param minimumSteps The amount of basic commands we already have executed. 
	 * @param currentSteps The amount of basic commands we already passed.
	 * @param robot The robot that will be manipulated by the given program.
	 * @effect One basic command, when their are still left, will be executed.
	 * 		| if minimumSteps == currentSteps
	 * 		|	then execute(robot)
	 * @return The new currentSteps which will increase when a basic command is found.
	 * 		| result == ++currentSteps
	 * @throws IllegalArgumentException
	 * 		When the robot is not valid when the execute method is invoked.
	 */
	@Override
	public int next(final int minimumSteps, int currentSteps, Robot robot) {
		if(minimumSteps == currentSteps)
			execute(robot);
		return ++currentSteps;
	}
	
	/**
	 * Returns a String representation of this ExecutionCommand.
	 * 
	 * @return The result is a String that begins with a opening bracket, followed by the name of the executionProcedure,
	 * 				followed by a String-representation of the arguments of this command, and that ends with a closing bracket.
	 * 		| let write = new String()
	 * 		| for each value in {this.getArguments}
	 * 		|	do write = write + " " + this.getExecutionProcedure().getArgument(value)
	 * 		| return "(" + this.getExecutionProcedure().toString() + write + ")"
	 */
	@Override
	public String write(String leftSpaces) {
		String write = new String();
		assert this.canHaveAsArguments(this.getArguments()); //must satisfy its class-invariants.
		for(Object value : this.getArguments())
			write = write + " " + this.getExecutionProcedure().getArgument(value); 
		return leftSpaces + "(" + this.getExecutionProcedure().toString() + write + ")\n";
	}

	/**
	 * An enum that stores the different procedures possible for an ExecutionCommand.
	 * 
	 * @author Molderez Tom, 2de bach Ingenieurswetenschappen Computerwetenschappen-Elektrotechniek and Reniers Jorn, 2de bach Ingenieurswetenschappen Werktuigkunde-Computerwetenschappen
	 * @version 3.0
	 *
	 */
	public enum ExecutionProcedure implements TextProcedure { 
		
		/**
		 * This procedure makes a Robot turn according the argument clockwise or counterclockwise if the
		 * robot can turn. (see Robot for constraints on turning).
		 */
		TURN{
			
			/**
			 * A constant for turning clockwise.
			 */
			private final String CLOCKWISE = "clockwise";
			
			/**
			 * A constant for turning counterclockwise.
			 */
			private final String COUNTERCLOCKWISE = "counterclockwise";
			
			/**
			 * Executes this turn command.
			 * 
			 * @param robot The robot that should execute this turn.
			 * @param arguments An array of object that are extra arguments that are needed, according to canHaveAsArguments.
			 * @effect If the robot can turn, see Robot, this robot turns in the given direction.
			 * 		| if PhysicalAmount.isValidAmount(robot.getEnergyLevel().getAmount() - DefaultConstants.ROBOT_ENERGY_TURN.getAmount())
					|		&& robot.canHaveAsEnergyLevel(robot.getEnergyLevel().subtract(DefaultConstants.ROBOT_ENERGY_TURN))
			 * 		|	then robot.turn( (Direction)arguments[0])
			 * @throws IllegalArgumentException
			 * 		| if the arguments are illegal according to canHaveAsArguments() or if the robot is illegal according to canHaveAsRobot()
			 * 		| !canHaveAsArguments(arguments) || !canHaveAsRobot(robot)
			 */
			@Override
			public void execute(Robot robot, Object... arguments)  throws IllegalArgumentException {
				if(!canHaveAsArguments(arguments) || !canHaveAsRobot(robot))
					throw new IllegalArgumentException("Turn should have one argument, a Direction, and an effective robot");
				if( PhysicalAmount.isValidAmount(robot.getEnergyLevel().getAmount() - DefaultConstants.ROBOT_ENERGY_TURN.getAmount())
						&& robot.canHaveAsEnergyLevel(robot.getEnergyLevel().subtract(DefaultConstants.ROBOT_ENERGY_TURN)) )
					robot.turn( (Direction)arguments[0]);
			}

			/**
			 * Controls if the given arguments are valid.
			 * 
			 * @param arguments The arguments to be controlled.
			 * @return The result is false if the arguments are null, or if the length of the arguments is not 1
			 * 			or if this doesn't contain (see containsObject()) the argument.
			 * 		result == (arguments != null && arguments.length == 1 && this.containsValue(arguments[0]))
			 */
			@Override
			public boolean canHaveAsArguments(Object... arguments) {
				return arguments != null && arguments.length == 1 && this.containsValue(arguments[0]);
			}

			/**
			 * Returns the pattern a String must match to be properly converted to this turn procedure.
			 * The pattern must be of the form: <(> <this.toString()> <clockwsise|counterclockwise> <)> with arbitrary
			 * white characters except for the beginning or ending.
			 */ 
			@Override @Basic @Immutable @Raw
			public String getStringPattern() {
				return "^(\\()(\\s*)(" + this.toString() + ")(\\s++)(" + CLOCKWISE + "|" + COUNTERCLOCKWISE + ")(\\s*)(\\))";
			}

			/**
			 * Returns a String representation of the given object if this procedure could contain the object.
			 * 
			 * @param value The value (Object) of which the corresponding argument (String) must be returned.
			 * @return If the argument is Direction.CLOCKWISE, the result is "clockwise", 
			 * 			if the argument is Direction.COUNTERCLOCKWISE, then the result is "counterclockwise".
			 * @throws IllegalArgumentException (repeated)
			 * 		When the value is not a valid argument
			 * 		| !containsValue(value)
			 * @note The meaning of the couple value (Object) and argument (String) is the following:
			 * If you would like to give the value (object) as an argument for this condition, than you
			 * should give the argument (String) as parameter in the program.
			 */
			@Override
			public String getArgument(Object value)
					throws IllegalArgumentException {
				if(value.equals(Direction.CLOCKWISE))
					return CLOCKWISE;
				else if(value.equals(Direction.COUNTERCLOCKWISE))
					return COUNTERCLOCKWISE;
				else
					throw new IllegalArgumentException("Could not convert the given value to a valid String-representation: " + value.toString());
			}

			
			/**
			 * Returns whether the value could be an argument of this TURN-ExecutionProcedure.
			 * 
			 * @param value The value of which a String representation must be returned.
			 * @return True if and only if value is equal to Direction.CLOCKWISE or to Direction.COUNTERCLOCKWISE.
			 */
			@Override
			public boolean containsValue(Object value) {
				if(value.equals(Direction.CLOCKWISE))
					return true;
				else if(value.equals(Direction.COUNTERCLOCKWISE))
					return true;
				return false;
			}

			/**
			 * Returns the object according the given String representation
			 * 
			 * @param argument The argument of which the object must be returned.
			 * @return When the argument equals "clockwise", Direction.CLOCKWISE will be returned, else when
			 * the argument equals "counterclockwise", Direction.COUNTERCLOCKWISE will be returned.
			 * @throws IllegalArgumentException
			 * 		When the given argument is not valid.
			 * 		| !containsArgument(argument)
			 */
			@Override
			public Object getValue(String argument) throws IllegalArgumentException {
				if(argument.equals(CLOCKWISE))
					return Direction.CLOCKWISE;
				else if(argument.equals(COUNTERCLOCKWISE))
					return Direction.COUNTERCLOCKWISE;
				else
					throw new IllegalArgumentException();
			}

			/**
			 * Controls if the given argument is valid for this ExecutionProcedure.
			 * 
			 * @param argument The argument to be controlled.
			 * @return True if argument equals "clockwise" or "counterclockwise".
			 */
			@Override
			public boolean containsArgument(String argument) {
				if(argument.equals(CLOCKWISE))
					return true;
				else if(argument.equals(COUNTERCLOCKWISE))
					return true;
				return false;
			}

		},
		
		/**
		 * Moves the robot one step in its given direction if possible. If he is on a board, other constraints must be
		 * checked. See Robot for more details concerning this restrictions.
		 */
		MOVE{

			/**
			 * Executes this move command.
			 * 
			 * @param robot The robot that should execute this movement.
			 * @param arguments An array of object that are extra arguments that are needed, according to canHaveAsArguments.
			 * @effect If the robot can move (see Robot), moves the robot one step (see Robot).
			 * 		| let temp be robot.getEnergyLevel().subtract(DefaultConstants.ROBOT_ENERGY_MOVEMENT.add( 
			 * 		|			DefaultConstants.ROBOT_ENERGY_MOVEMENT_PER_WEIGHT.multiply(robot.getWeightCarried().getAmount()) ))
			 * 		| if temp.getAmount >= 0 && robot.canHaveAsEnergyLevel(temp) && !robot.isTerminated()
			 * 		|	then if robot.getOrientation() == Orientation.UP
			 * 		|		then if Position.isValidX(robot.getPosition().getX()) && Position.isValidY(robot.getPosition().getY() - 1)
			 * 		|			then if robot.canHaveAsPosition(robot.getPosition().move(robot.getOrientation()))
			 * 		|				then robot.move()
			 * 		|   else if robot.getOrientation() == Orientation.RIGHT
			 * 		|		then if Position.isValidX(robot.getPosition().getX() + 1) && Position.isValidY(robot.getPosition().getY())
			 * 		|			then if robot.canHaveAsPosition(robot.getPosition().move(robot.getOrientation()))
			 * 		|				then robot.move()
			 * 		|	else if robot.getOrientation() == Orientation.DOWN
			 * 		|		then if Position.isValidX(robot.getPosition().getX()) && Position.isValidY(robot.getPosition().getY() + 1)
			 * 		|			then if robot.canHaveAsPosition(robot.getPosition().move(robot.getOrientation()))
			 * 		|				then robot.move()
			 * 		|	else if robot.getOrientation() == Orientation.LEFT
			 * 		|		then if Position.isValidX(robot.getPosition().getX() - 1) && Position.isValidY(robot.getPosition().getY())
			 * 		|			then if robot.canHaveAsPosition(robot.getPosition().move(robot.getOrientation()))
			 * 		|				then robot.move()   
			 * @throws IllegalArgumentException
			 * 		| if the arguments are illegal according to canHaveAsArguments() or if the robot is illegal according to canHaveAsRobot()
			 * 		| !canHaveAsArguments(arguments) || !canHaveAsRobot(robot)
			 */
			@Override
			public void execute(Robot robot, Object... arguments)  throws IllegalArgumentException {
				if(!canHaveAsArguments(arguments) || !canHaveAsRobot(robot))
					throw new IllegalArgumentException("Move should have no arguments and an effective robot");
				if( PhysicalAmount.isValidAmount( robot.getEnergyLevel().getAmount() - DefaultConstants.ROBOT_ENERGY_MOVEMENT.getAmount()
						- PhysicalAmountFactory.get().create(robot.getWeightCarried().getAmount() * DefaultConstants.ROBOT_ENERGY_MOVEMENT_PER_WEIGHT, Unit.WATTSECOND).getAmount()) ){
					PhysicalAmount temp = robot.getEnergyLevel().subtract(DefaultConstants.ROBOT_ENERGY_MOVEMENT,
							PhysicalAmountFactory.get().create(robot.getWeightCarried().getAmount() * DefaultConstants.ROBOT_ENERGY_MOVEMENT_PER_WEIGHT, Unit.WATTSECOND));
					if(robot.canHaveAsEnergyLevel(temp)){
						try{
							robot.move();
						}
						catch(IllegalStateException e1){} //robot cannot move, nothing must happen
						catch(IllegalPositionException e2){}
						catch(IllegalPositionOnBoardException e3){}
					}
				}
			}

			/**
			 * Controls if the given arguments are valid.
			 * 
			 * @param arguments The arguments to be controlled.
			 * @return True if the arguments are null or if the length of the arguments is 0.
			 * 		result == (arguments == null || arguments.length == 0)
			 */
			@Override
			public boolean canHaveAsArguments(Object... arguments) {
				return arguments == null || arguments.length == 0;
			}

			/**
			 * Returns a String representation of the given value as argument if valid.
			 * 
			 * @param value The value of which a String representation must be returned.
			 * @return Will never occur.
			 * @throws IllegalArgumentException
			 * 		Will always occur because this does not have a valid argument.
			 * 		| true
			 */
			@Override
			public String getArgument(Object value)
					throws IllegalArgumentException {
				if(!containsValue(value))
					throw new IllegalArgumentException();
				assert false;
				return null;
			}

			/**
			 * Controls if this can have the value as argument.
			 * 
			 * @param value The value to be controlled.
			 * @return Always false. This can not have an argument.
			 */
			@Override
			public boolean containsValue(Object value) {
				return false;
			}

			/**
			 * Returns the object of which the given String is the source code.
			 * 
			 * @param argument The argument of which the object must be returned.
			 * @return Will never occur.
			 * @throws IllegalArgumentException
			 * 		Will always occur because this does not have a valid argument.
			 * 		| true
			 */
			@Override
			public Object getValue(String argument) {
				if(!containsArgument(argument))
					throw new IllegalArgumentException();
				assert false;
				return null;
			}

			/**
			 * Controls if this can have the argument as value.
			 * 
			 * @param argument The argument to be controlled.
			 * @return Always false. This can not have an argument.
			 */
			@Override
			public boolean containsArgument(String argument) {
				return false;
			}
			
		},
		
		/**
		 * The robot will shoot in his direction according the shoot specification in Robot.
		 */
		SHOOT{

			/**
			 * Executes this shoot command.
			 * 
			 * @param robot The robot that should execute this shooting.
			 * @param arguments An array of object that are extra arguments that are needed, according to canHaveAsArguments.
			 * @effect Makes the robot shoot as in Robot.
			 * 		| robot.shoot()
			 * @throws IllegalArgumentException
			 * 		| if the arguments are illegal according to canHaveAsArguments() or if the robot is illegal according to canHaveAsRobot()
			 * 		| !canHaveAsArguments(arguments) || !canHaveAsRobot(robot)
			 */
			@Override
			public void execute(Robot robot, Object... arguments)  throws IllegalArgumentException {
				if(!canHaveAsArguments(arguments) || !canHaveAsRobot(robot))
					throw new IllegalArgumentException("Shoot should have no arguments and an effective robot");
				robot.shoot();
			}

			/**
			 * Controls if the given arguments are valid.
			 * 
			 * @param arguments The arguments to be controlled.
			 * @return True if the arguments are null or if the length of the arguments is 0.
			 * 		result == (arguments == null || arguments.length == 0)
			 */
			@Override
			public boolean canHaveAsArguments(Object... arguments) {
				return arguments == null || arguments.length == 0;
			}
			
			/**
			 * Returns a String representation of the given value as argument if valid.
			 * 
			 * @param value The value of which a String representation must be returned.
			 * @return Will never occur.
			 * @throws IllegalArgumentException
			 * 		Will always occur because this does not have a valid argument.
			 * 		| true
			 */
			@Override
			public String getArgument(Object value)
					throws IllegalArgumentException {
				if(!containsValue(value))
					throw new IllegalArgumentException();
				assert false;
				return null;
			}

			/**
			 * Controls if this can have the value as argument.
			 * 
			 * @param value The value to be controlled.
			 * @return Always false. This can not have an argument.
			 */
			@Override
			public boolean containsValue(Object value) {
				return false;
			}

			/**
			 * Returns the object of which the given String is the source code.
			 * 
			 * @param argument The argument of which the object must be returned.
			 * @return Will never occur.
			 * @throws IllegalArgumentException
			 * 		Will always occur because this does not have a valid argument.
			 * 		| true
			 */
			@Override
			public Object getValue(String argument) {
				if(!containsArgument(argument))
					throw new IllegalArgumentException();
				assert false;
				return null;
			}

			/**
			 * Controls if this can have the argument as value.
			 * 
			 * @param argument The argument to be controlled.
			 * @return Always false. This can not have an argument.
			 */
			@Override
			public boolean containsArgument(String argument) {
				return false;
			}
		},
		
		/**
		 * The robot will try to pickup and use an item at his current position. Therefore the robot
		 * must have a board. Otherwise noting happens. If there is no usable item present, nothing
		 * happens either.
		 */
		PICKUP_AND_USE{

			/**
			 * Executes this pickup-and-use command.
			 * 
			 * @param robot The robot that should execute this pickup-and-use command.
			 * @param arguments An array of object that are extra arguments that are needed, according to canHaveAsArguments.
			 * @effect If the robot can pick up an item (see Robot), let him pick it up and use it.
			 * 		| if robot.getBoard() != null
			 * 		|	then for one usable in {robot.getBoard().getItemsAtType(Usable.class, robot.getPosition())}
			 * 		|		 	robot.pickUp(usable)
			 * 		|			robot.use(usable)
			 * @throws IllegalArgumentException
			 * 		| if the arguments are illegal according to canHaveAsArguments() or if the robot is illegal according to canHaveAsRobot()
			 * 		| !canHaveAsArguments(arguments) || !canHaveAsRobot(robot)
			 */
			@Override
			public void execute(Robot robot, Object... arguments)  throws IllegalArgumentException {
				if(!canHaveAsArguments(arguments) || !canHaveAsRobot(robot))
					throw new IllegalArgumentException("Pickup-and-use should have no arguments and an effective robot");	
				else if(robot.getBoard() != null) {
					try { 
						UsableWithBoard usable = robot.getBoard().getItemsAtType(UsableWithBoard.class, robot.getPosition()).iterator().next();
						robot.pickUp(usable); //Total
						robot.use(usable);	//Total
					} catch(NoSuchElementException exc) { //nothing in the list of usable items at the robot's position, nothing must happen.
					}
				}
			}
			
			/**
			 * Controls if the given arguments are valid.
			 * 
			 * @param arguments The arguments to be controlled.
			 * @return True if the arguments are null or if the length of the arguments is 0.
			 * 		result == (arguments == null || arguments.length == 0)
			 */
			@Override
			public boolean canHaveAsArguments(Object... arguments) {
				return arguments == null || arguments.length == 0;
			}
			
			/**
			 * Returns a String representation of the given value as argument if valid.
			 * 
			 * @param value The value of which a String representation must be returned.
			 * @return Will never occur.
			 * @throws IllegalArgumentException
			 * 		Will always occur because this does not have a valid argument.
			 * 		| true
			 */
			@Override
			public String getArgument(Object value)
					throws IllegalArgumentException {
				if(!containsValue(value))
					throw new IllegalArgumentException();
				assert false;
				return null;
			}

			/**
			 * Controls if this can have the value as argument.
			 * 
			 * @param value The value to be controlled.
			 * @return Always false. This can not have an argument.
			 */
			@Override
			public boolean containsValue(Object value) {
				return false;
			}

			/**
			 * Returns the object of which the given String is the source code.
			 * 
			 * @param argument The argument of which the object must be returned.
			 * @return Will never occur.
			 * @throws IllegalArgumentException
			 * 		Will always occur because this does not have a valid argument.
			 * 		| true
			 */
			@Override
			public Object getValue(String argument) {
				if(!containsArgument(argument))
					throw new IllegalArgumentException();
				assert false;
				return null;
			}

			/**
			 * Controls if this can have the argument as value.
			 * 
			 * @param argument The argument to be controlled.
			 * @return Always false. This can not have an argument.
			 */
			@Override
			public boolean containsArgument(String argument) {
				return false;
			}
		};
		
		/**
		 * Executes this command.
		 * 
		 * @param robot The robot that should execute this program.
		 * @param arguments An array of object that are extra arguments that may be needed.
		 * @throws IllegalArgumentException
		 * 		When the arguments are not valid according to canHaveAsArguments().
		 * 		| !canHaveAsArguments(arguments)
		 * @throws IllegalArgumentException
		 * 		When the robot is not valid according to canHaveAsRobot().
		 * 		| !canHaveAsRobot(robot)
		 */
		public void execute(Robot robot, Object...arguments) throws IllegalArgumentException {
			if(!canHaveAsArguments(arguments) || !canHaveAsRobot(robot)) 
				throw new IllegalArgumentException("Illegal argument or IllegalRobot");
		}
		
		/**
		 * Returns a textual representation of this executionProcedure.
		 * 
		 * @return The result is a String equal to the name of the enum-literal but with lower cases and with - in stead of _
		 * 		| result == super.toString().toLowerCase().replaceAll("_", "-")
		 */
		@Raw @Override
		public final String toString() {
			return super.toString().toLowerCase().replaceAll("_", "-");
		}
		
		/**
		 * Controls if this arguments are valid.
		 * 
		 * @param arguments The arguments to be controlled.
		 */
		@Raw
		public abstract boolean canHaveAsArguments(Object... arguments);
		
		/**
		 * Controls if the robot is valid.
		 * 
		 * @param robot The robot to be controlled.
		 * @return If the robot is null, the result is false.
		 * 		| if robot == null
		 * 		|	then result == false
		 * @return If the robot is terminated, the result is false.
		 * 		| if robot.isTerminated()
		 * 		|	then result == false
		 */
		@Raw
		public boolean canHaveAsRobot(Robot robot) {
			return robot != null && !robot.isTerminated();
		}
				
		/**
		 * Returns the String pattern of a command with no arguments.
		 * The pattern is of the form: <(> <this.toString()> <)> with
		 * arbitrary white characters except for the beginning and ending.
		 */
		@Override @Basic @Raw @Immutable
		public String getStringPattern() {
			return "^(\\()(\\s*)(" + this.toString() + ")(\\s*)(\\))";
		}	
	}

}


